package com.sojson.util.security.shiro.interceptor.impl;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;

import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.aop.AuthorizingAnnotationHandler;
import org.apache.shiro.subject.Subject;

import com.sojson.config.exception.TransErrorCode;
import com.sojson.config.exception.TransNoException;
import com.sojson.constant.ConstantByMap;
import com.sojson.util.filter.FilterUtil;
import com.sojson.util.security.shiro.annotation.RequiredRole;
import com.sojson.util.servlet.ServletUtil;

/**
 * 角色注解实际处理类
 * 
 * @author liu
 * @date 2020-11-02
 */
public class RequiredRoleAnnotationHandler extends AuthorizingAnnotationHandler {

    public RequiredRoleAnnotationHandler() {
        // 告诉shiro这个处理器处理哪个注解
        super(RequiredRole.class);
        System.out.println("拦截器:RequiredRoleAnnotationHandler:RequiredRoleAnnotationHandler");
    }

    /**
     * 获取注解中value的所有值
     * 
     * @param a
     * @return
     */
    private List<String> getAnnotationValue(Annotation a) {
        System.out.println("拦截器:RequiredRoleAnnotationHandler:getAnnotationValue");
        RequiredRole rrAnnotation = (RequiredRole)a;
        return Arrays.asList(rrAnnotation.value());
    }

    /**
     * 主要方法
     */
    @Override
    public void assertAuthorized(Annotation a) throws AuthorizationException {
        System.out.println("拦截器:RequiredPermissionAnnotationHandler:assertAuthorized");
        // 方法上的注解是否是这个注解,如果不是就不做处理
        if (!(a instanceof RequiredRole)) {
            return;
        }

        RequiredRole rrAnnotation = (RequiredRole)a;
        // 获取注解中的所有角色
        List<String> roles = getAnnotationValue(a);
        Subject subject = getSubject();
        // 如果注解中只有一个value就只判断一个
        if (roles.size() == 1) {
            // 如不包含果注解中的角色就抛异常
            if (!subject.hasRole(roles.get(0))) {
                try {
                    if (subject.isAuthenticated()) {
                        FilterUtil.responseDate(ServletUtil.getHttpServletRequest(),
                            ServletUtil.getHttpServletResponse(), TransErrorCode.NOT_USER_PERMISSION,
                            ConstantByMap.CONTROLLER_URL_OPEN_UNAUTHORIZED_URL_ALL);
                    } else {
                        FilterUtil.responseDate(ServletUtil.getHttpServletRequest(),
                            ServletUtil.getHttpServletResponse(), TransErrorCode.NOT_LOGIN,
                            ConstantByMap.CONTROLLER_URL_OPEN_LOGIN_URL_ALL);
                    }
                } catch (IOException e) {
                }
                throw new TransNoException();
            }
            return;
        }

        // 多个角色是并且关系
        if (Logical.AND.equals(rrAnnotation.logical())) {
            // 如果注解中的所有角色都不包含就抛异常
            if (!subject.hasAllRoles(roles)) {
                try {
                    if (subject.isAuthenticated()) {
                        FilterUtil.responseDate(ServletUtil.getHttpServletRequest(),
                            ServletUtil.getHttpServletResponse(), TransErrorCode.NOT_USER_PERMISSION,
                            ConstantByMap.CONTROLLER_URL_OPEN_UNAUTHORIZED_URL);
                    } else {
                        FilterUtil.responseDate(ServletUtil.getHttpServletRequest(),
                            ServletUtil.getHttpServletResponse(), TransErrorCode.NOT_LOGIN,
                            ConstantByMap.CONTROLLER_URL_OPEN_LOGIN_URL);
                    }
                } catch (IOException e) {
                }
                throw new TransNoException();
            }
            return;
        }

        // 多个角色是或者关系
        if (Logical.OR.equals(rrAnnotation.logical())) {
            // 定义是否包含某个角色
            boolean hasAtLeastOneRole = false;
            // 遍历注解中的所有角色
            for (String role : roles) {
                // 有一个是true就通过
                if (subject.hasRole(role)) {
                    hasAtLeastOneRole = true;
                    break;
                }
            }
            // 如果不包含任意一个角色就抛异常
            if (!hasAtLeastOneRole) {
                try {
                    if (subject.isAuthenticated()) {
                        FilterUtil.responseDate(ServletUtil.getHttpServletRequest(),
                            ServletUtil.getHttpServletResponse(), TransErrorCode.NOT_USER_PERMISSION,
                            ConstantByMap.CONTROLLER_URL_OPEN_UNAUTHORIZED_URL);
                    } else {
                        FilterUtil.responseDate(ServletUtil.getHttpServletRequest(),
                            ServletUtil.getHttpServletResponse(), TransErrorCode.NOT_LOGIN,
                            ConstantByMap.CONTROLLER_URL_OPEN_LOGIN_URL);
                    }
                } catch (IOException e) {
                }
                throw new TransNoException();
            }
        }

    }

}